/*
  "This product includes software developed by
       TouchGraph LLC (http://www.touchgraph.com/)."
 */
package abdn.graph.ontobrowser;

import com.touchgraph.graphlayout.TGPanel;
import java.io.*;
import java.awt.*;
import java.awt.geom.*;

/**  OBEdge:  A LinkBrowser Edge.  Extends edge by adding different edge types, specifically a bidirectional
 *  edge type rendered as a thin line.
 *
 *  @author   Alexander Shapiro  , Serguei Krivov
 *  @version  1.20
 */

public class OBEdge
    extends com.touchgraph.graphlayout.Edge {

  public final static int START_EDGE = 0;
  public final static int END_EDGE = 1;
  public final static int ARGUMENT_EDGE = 2;
  public final static int SUBCLASS_OF_EDGE = 3;
  public final static int INSTANCE_OF_EDGE = 4;
  public final static int EQUIVALENT_EDGE = 5;
  public final static int SPECIAL_EDGE = 6;
  public int edgeOrder;

  private boolean inferred = false;

  public OBEdge(OBNode f, OBNode t, int order) {
      this(f, t, DEFAULT_LENGTH, order, null);
    }

  public OBEdge(OBNode f, OBNode t, int order, Color color) {
    this(f, t, DEFAULT_LENGTH, order, color);
  }

  public OBEdge(OBNode f, OBNode t, int len, int order, Color c) {
    super(f, t, len, c);
    //col=UNDEFRELATION_EDGE_COLOR;
    edgeOrder = order;
    /* if(edgeOrder==START_EDGE)
        type = OBConfig.ATTR_START_TYPE;
     else
         type = OBConfig.ATTR_END_TYPE;*/
    if (edgeOrder == SUBCLASS_OF_EDGE || edgeOrder == INSTANCE_OF_EDGE) {
      distance = 2;
    }

  }

  /*
     public void resetCategory(int relationCategory, boolean inheritable, boolean multy, boolean isvariable  ) {
          if(edgeOrder==START_EDGE)
          {
              switch(relationCategory) {
                  case OBRelationNode.IS_SUBCLASS:
                      {  type = OBConfig.ISA_START_TYPE; col =OBConfig.ISA_SUBCLASS_EDGE_COLOR;  return;}
                  case OBRelationNode.IS_INSTANCE:
                      {  type = OBConfig.ISA_START_TYPE; col =OBConfig.ISA_INSTANCE_EDGE_COLOR;  return;}
                  case OBRelationNode.IS_ATTRIBUTE:
                      {
                          type = OBConfig.ATTR_START_TYPE;
                          if(inheritable) edgeTile=OBConfig.INHATTR_TILE;
                          if(isvariable) col=OBConfig.VAR_ATTRIB_EDGE_COLOR; else col=OBConfig.ATTRIB_EDGE_COLOR;
                          return;
                       }
                  case OBRelationNode.IS_SIGNATURE:
                       {
                          type = OBConfig.SIGN_START_TYPE;
                          if(inheritable) edgeTile=OBConfig.INHSIGN_TILE;
                          if(isvariable) col=OBConfig.VAR_SIGN_EDGE_COLOR; else col=OBConfig.SIGN_EDGE_COLOR;
                          return;
                       }
                  case OBRelationNode.IS_DISJOINT_WITH:
                  case OBRelationNode.IS_SAME_AS:
                  {
                    type = OBConfig.CONSTRAINT_ATTRIBUTE_START_TYPE;
                    col=OBConfig.CONSTRAINT_EDGE_COLOR;
                    return;
                  }
                  case OBRelationNode.IS_INTERSECTION:
                  case OBRelationNode.IS_UNION:
                  case OBRelationNode.IS_DISJOINT:
                  case OBRelationNode.IS_DISJOINT_UNION:
                  case OBRelationNode.IS_ONE_OF:
                  {
                    type = OBConfig.CONSTRAINT_OPERATOR_START_TYPE;
                    col=OBConfig.CONSTRAINT_EDGE_COLOR;
                    return;
                  }
              }
          }
          else
          {
              switch(relationCategory) {
                  case OBRelationNode.IS_SUBCLASS:
                      {  type = OBConfig.ISA_END_TYPE; col =OBConfig.ISA_SUBCLASS_EDGE_COLOR;  return;}
                  case OBRelationNode.IS_INSTANCE:
                      {  type = OBConfig.ISA_END_TYPE; col =OBConfig.ISA_INSTANCE_EDGE_COLOR;  return;}
                  case OBRelationNode.IS_ATTRIBUTE:
                      {
       if(multy) type=OBConfig.MULTYATTR_END_TYPE; else  type = OBConfig.ATTR_END_TYPE;
                          if(isvariable) col=OBConfig.VAR_ATTRIB_EDGE_COLOR; else col=OBConfig.ATTRIB_EDGE_COLOR;
                          return;
                       }
                  case OBRelationNode.IS_SIGNATURE:
                       {
       if(multy) type=OBConfig.MULTYSIGN_END_TYPE; else  type = OBConfig.SIGN_END_TYPE;
                           if(isvariable) col=OBConfig.VAR_SIGN_EDGE_COLOR; else col=OBConfig.SIGN_EDGE_COLOR;
                          return;
                       }
                  case OBRelationNode.IS_DISJOINT_WITH:
                  case OBRelationNode.IS_SAME_AS:
                  {
                    type = OBConfig.CONSTRAINT_ATTRIBUTE_END_TYPE;
                    col=OBConfig.CONSTRAINT_EDGE_COLOR;
                    return;
                  }
                  case OBRelationNode.IS_INTERSECTION:
                  case OBRelationNode.IS_UNION:
                  case OBRelationNode.IS_DISJOINT:
                  case OBRelationNode.IS_DISJOINT_UNION:
                  case OBRelationNode.IS_ONE_OF:
                  {
                    type = OBConfig.CONSTRAINT_OPERATOR_END_TYPE;
                    col=OBConfig.CONSTRAINT_EDGE_COLOR;
                    return;
                  }
              }
          }
     }
   */

  public static void setEdgeDafaultType(int type) {
    DEFAULT_TYPE = type;
  }

  public static void paintFatLine(Graphics g, int x1, int y1, int x2, int y2,
                                  Color c) {
    g.setColor(c);
    g.drawLine(x1, y1, x2, y2);
    g.drawLine(x1 + 1, y1, x2 + 1, y2);
    g.drawLine(x1 + 1, y1 + 1, x2 + 1, y2 + 1);
    g.drawLine(x1, y1 + 1, x2, y2 + 1);
  }

  /*
      public static void paint(Graphics g, int x1, int y1, int x2, int y2, Color c, int type) {
          switch (type) {
       case BIDIRECTIONAL_EDGE:   paintFatLine(g, x1, y1, x2, y2, c); break;
       case HIERARCHICAL_EDGE:  paintArrow(g, x1, y1, x2, y2, c);  break;
          }
      }
   public void paint(Graphics g, TGPanel tgPanel) {
          Color c;
          if (tgPanel.getMouseOverN()==from || tgPanel.getMouseOverE()==this)
              c = MOUSE_OVER_COLOR;
          else
              c = col;
    int x1=(int) from.drawx;
    int y1=(int) from.drawy;
    int x2=(int) to.drawx;
    int y2=(int) to.drawy;
    if (intersects(tgPanel.getSize())) {
              paint(g, x1, y1, x2, y2, c, edgeType);
    }
   }
   */

  public static void paintGhost(Graphics g, double x1, double y1, double x2,
                                double y2, Color c) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setPaint(c);
    g2.setStroke(dashed);
    g2.draw(new Line2D.Double(x1, y1, x2, y2));

    double l = Math.sqrt( (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
    double xa = x2 - arr * (x2 - x1) / l;
    double ya = y2 - arr * (y2 - y1) / l;

    if (Math.abs(y2 - y1) > 1) {
      double k = (x2 - x1) / (y2 - y1);
      double dx = arw / Math.sqrt(1 + k * k);
      double dy = k * dx;

      /*
                     g2.draw(new Line2D.Double(xa+dx ,ya-dy, x2, y2));
                     g2.draw(new Line2D.Double(xa-dx ,ya+dy,    x2, y2));
       */
      double ix2 = xa + dx;
      double iy2 = ya - dy;
      double ix3 = xa - dx;
      double iy3 = ya + dy;
      Polygon arrow = new Polygon();
      arrow.addPoint( (int) x2, (int) y2);
      arrow.addPoint( (int) ix2, (int) iy2);
      arrow.addPoint( (int) ix3, (int) iy3);
      g2.fill(arrow);

    }
    else {
      /*
                    g2.draw(new Line2D.Double(xa, ya+arw, x2, y2));
                    g2.draw(new Line2D.Double(xa, ya-arw,   x2, y2));
       */

      double iy2 = ya + arw;
      double iy3 = ya - arw;
      Polygon arrow = new Polygon();
      arrow.addPoint( (int) x2, (int) y2);
      arrow.addPoint( (int) xa, (int) iy2);
      arrow.addPoint( (int) xa, (int) iy3);
      g2.fill(arrow);
    }
  }

  /**
   * Method isInferred
   * @return
   */
  public boolean isInferred() {
    return inferred;
  }

  /**
   * Method setInferred
   * @param b
   */
  public void setInferred(boolean b) {
    inferred = b;
  }

}